package com.lemon.core.common.lang.xml;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lemon.core.common.lang.template.VmGrammarTemplate;
import com.lemon.core.common.lang.xml.entity.XmlTmplAttr;
import com.lemon.core.common.lang.xml.entity.XmlTmplEle;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.dom.DOMCDATA;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @author hdzhang
 * @ClassName Dom4jUtils
 * @desc dom4j工具类
 * @Date 2018/8/27 14:57
 * @Version 1.0
 **/
public class Dom4jUtils {

    public interface Constants {
        /**
         * vm for循环
         */
        public final static int VM_TMPL_TYPE_FOR = 1;

        /**
         * vm if条件
         */
        public final static int VM_TMPL_TYPE_IF = 2;

        /**
         * 换行符
         */
        public final static String BREAK_LINE = "\n";

        /**
         * 制表位
         */
        public final static String TAB_STOP = "\t";

        /**
         * utf-8 字编码
         */
        public final static String UTF_8 = "UTF-8";
    }

    public static JSONArray parseList(File file) {
        JSONArray jsonArray = new JSONArray();

        SAXReader reader = new SAXReader();
        Document document = null;
        try {
            document = reader.read(file);
            Element rootNode = document.getRootElement();

        } catch (DocumentException e) {
            e.printStackTrace();
        }

        return jsonArray;
    }

    private static JSONObject parseObject(Element element) {
        JSONObject jsonObject = new JSONObject();
        return jsonObject;
    }

    /**
     * 用模板数据生成vm模板文件
     * @param file  模板文件
     * @param xmlTmplData  模板数据
     */
    public static void writeXmlVmFile(File file, XmlTmplEle xmlTmplData) {
        // 1、创建文档
        Document document = DocumentHelper.createDocument();

        // 2、生成根节点
        Element root = createRootEle(document, xmlTmplData);

        // 3、递归生成所有子节点
        deppCreateEle(root, xmlTmplData);

        // 4、写xml文件
        XMLWriter writer = null;
        try {
            OutputFormat format = OutputFormat.createPrettyPrint();
            // 设置换行符
            format.setLineSeparator(Constants.BREAK_LINE);
            format.setTrimText(false);
            format.setIndent(Constants.TAB_STOP);

            writer =new XMLWriter(new FileOutputStream(file), format);
            // 字符是否转义，默认true
            writer.setEscapeText(false);
            writer.write(document);
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != writer) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 递归创建子节点
     * @param parentELe
     * @param xmlTmplData
     */
    private static void deppCreateEle(Element parentELe, XmlTmplEle xmlTmplData) {
        if (null != xmlTmplData.getChildren()) {
            for (XmlTmplEle ele : xmlTmplData.getChildren()) {
                // 生成当前节点
                Element currentEle = createElement(parentELe, ele);
                // 递归生成子节点
                deppCreateEle(currentEle, ele);
            }
        }
    }

    /**
     * 创建根节点
     * @param document
     * @param xmlTmplData
     * @return
     */
    private static Element createRootEle(Document document, XmlTmplEle xmlTmplData) {
        // 1、创建根节点
        Element root = document.addElement(xmlTmplData.getEleName());

        // 2、设置根节点数据
        if (StringUtils.isNotBlank(xmlTmplData.getEleVal())) {
            root.setText(xmlTmplData.getEleVal());
        }
        // 3、设置根节点属性
        if (null != xmlTmplData.getAttrs()) {
            for (XmlTmplAttr attr : xmlTmplData.getAttrs()) {
                // 非空校验
                root.addAttribute(attr.getAttrName(), attr.getAttrVal());
            }
        }

        return root;
    }

    /**
     * 根据map数据创建节点
     * @param xmlTmplEle
     * @return
     */
    private static Element createElement(Element parentEle, XmlTmplEle xmlTmplEle) {

        // start grammar
        if (null != xmlTmplEle.getTmplType()) {
            switch (xmlTmplEle.getTmplType().intValue()) {
                case Constants.VM_TMPL_TYPE_FOR:
                    parentEle.addText(Constants.BREAK_LINE + VmGrammarTemplate.VM_TMPL_FOR.getStartGrammar()
                            + "($item in " + xmlTmplEle.getTmplPlace() + ")");
                    break;
                case Constants.VM_TMPL_TYPE_IF:
                    parentEle.addText(Constants.BREAK_LINE + VmGrammarTemplate.VM_TMPL_IF.getStartGrammar()
                            + "(" + xmlTmplEle.getEleVal() + ")");
                    break;
                default:
                    break;
            }
        }

        Element element = parentEle.addElement(xmlTmplEle.getEleName());

        // 设置当前节点的text
        if (StringUtils.isNotBlank(xmlTmplEle.getEleVal())) {

            if (null != xmlTmplEle.getIsCdata() && 1 == xmlTmplEle.getIsCdata()) {
                DOMCDATA cData = new DOMCDATA(xmlTmplEle.getEleVal());
                element.add(cData);
            } else {
                element.setText(xmlTmplEle.getEleVal());
            }
        }

        // 设置当前节点的attrs
        if (null != xmlTmplEle.getAttrs()) {
            for (XmlTmplAttr attr : xmlTmplEle.getAttrs()) {
                // 非空校验
                element.addAttribute(attr.getAttrName(), attr.getAttrVal());
            }
        }

        // end grammar
        if (null != xmlTmplEle.getTmplType()) {
            switch (xmlTmplEle.getTmplType().intValue()) {
                case Constants.VM_TMPL_TYPE_FOR:
                    parentEle.addText(Constants.BREAK_LINE + VmGrammarTemplate.VM_TMPL_FOR.getEndGrammar());
                    break;
                case Constants.VM_TMPL_TYPE_IF:
                    parentEle.addText(Constants.BREAK_LINE + VmGrammarTemplate.VM_TMPL_IF.getEndGrammar());
                    break;
                default:
                    break;
            }
        }

        return element;
    }

    /**
     * 模板缩进动态制表位
     * @param repeatNum
     * @return
     */
    private static String getRepeatTab(Integer repeatNum) {
        StringBuffer buffer = new StringBuffer();

        for (int i = 0; i < repeatNum; i++) {
            buffer.append(Constants.TAB_STOP);
        }

        return buffer.toString();
    }
}
